package exec

import (
	"bytes"
	"crypto/tls"
	"encoding/json"
	"fmt"
	"io"
	"net/http"

	"openeuler.org/PilotGo/PilotGo-plugin-automation/internal/module/job_history/model"
)

type Job struct {
	JobId         string `json:"job_id"`
	OperationType string `json:"operation_type"`
	JobType       string `json:"job_type"`
	Tag           string `json:"tag"`
	UsageType     string `json:"usage_type"`
	ExecCode      string `json:"exec_code"`
	JobStatus     string `json:"job_status"`
}

type JobParams struct {
	JobId string          `json:"job_id"`
	Name  string          `json:"name"`
	Type  string          `json:"type"`
	Value json.RawMessage `json:"value"`
}

type JobOutputParams struct {
	JobId string          `json:"job_id"`
	Name  string          `json:"name"`
	Type  string          `json:"type"`
	Value json.RawMessage `json:"value"`
}

type SubJob struct {
	JobId    string `json:"job_id"`
	StepNum  int    `json:"step_num"`
	StepType string `json:"step_type"`

	Dependencies []int `json:"dependencies"`

	ScriptId      string `json:"script_id"`
	ScriptType    string `json:"script_type"`
	ScriptParam   string `json:"script_param"`
	ScriptContent string `json:"script_content"`
	ScriptTimeout int    `json:"script_timeout"`

	StartTime    int64           `json:"start_time"`
	EndTime      int64           `json:"end_time"`
	SubJobStatus string          `json:"sub_job_status"`
	Result       json.RawMessage `json:"result"`
}

type JobTask struct {
	Job          Job               `json:"job"`
	InputParams  []JobParams       `json:"input_params"`
	OutputParams []JobOutputParams `json:"output_params"`
	SubJobs      []SubJob          `json:"sub_jobs"`
}

func ExecJob(ip string, jt JobTask) error {
	addr := fmt.Sprintf("http://%s:8277/plugin/automation/exec/job", ip)
	dataMarshed, err := json.Marshal(jt)
	if err != nil {
		return err
	}
	request, err := http.NewRequest("POST", addr, bytes.NewBuffer(dataMarshed))
	if err != nil {
		return err
	}
	request.Header.Set("Content-Type", "application/json")
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	response, err := client.Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		return err
	}

	var result struct {
		Message string      `json:"message"`
		Code    int         `json:"code"`
		Data    interface{} `json:"data"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("解析响应体失败: %s", err.Error())
	}
	if result.Code != http.StatusOK {
		return fmt.Errorf("作业任务下发失败, 报错: %s", result.Message)
	}
	return nil
}

type JobResult struct {
	JobId        string                  `json:"job_id"`
	ExecCode     string                  `json:"exec_code"`
	JobStatus    string                  `json:"job_status"`
	CurrentStep  int                     `json:"current_step"`
	Tag          string                  `json:"tag"`
	UsageType    string                  `json:"usage_type"`
	IP           string                  `json:"ip"`
	SubJobs      map[int]SubJob          `json:"sub_jobs"` // key=step_num
	InputParams  []model.JobParams       `json:"input_params"`
	OutputParams []model.JobOutputParams `json:"output_params"`
}

func GetJobResult(ip string, jobId string) (JobResult, error) {
	addr := fmt.Sprintf("http://%s:8277/plugin/automation/exec/job/result", ip)
	dataMarshed, err := json.Marshal(struct {
		JobId string `json:"job_id"`
	}{
		JobId: jobId,
	})
	if err != nil {
		return JobResult{}, err
	}
	request, err := http.NewRequest("POST", addr, bytes.NewBuffer(dataMarshed))
	if err != nil {
		return JobResult{}, err
	}
	request.Header.Set("Content-Type", "application/json")
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	response, err := client.Do(request)
	if err != nil {
		return JobResult{}, err
	}
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		return JobResult{}, err
	}

	var result struct {
		Message string    `json:"message"`
		Code    int       `json:"code"`
		Data    JobResult `json:"data"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return JobResult{}, fmt.Errorf("解析响应体失败: %s", err.Error())
	}
	if result.Code != http.StatusOK {
		return JobResult{}, fmt.Errorf("作业任务结果获取失败, 报错: %s", result.Message)
	}
	return result.Data, nil
}

func ResumeManualJob(ip string, resumeReq *model.TaskResumeRequest) error {
	addr := fmt.Sprintf("http://%s:8277/plugin/automation/exec/job/resume", ip)
	dataMarshed, err := json.Marshal(struct {
		JobId   string `json:"job_id"`
		StepNum int    `json:"step_num"`
		Action  string `json:"action"`
	}{
		JobId:   resumeReq.JobId,
		StepNum: resumeReq.StepNum,
		Action:  resumeReq.Action,
	})
	if err != nil {
		return err
	}
	request, err := http.NewRequest("POST", addr, bytes.NewBuffer(dataMarshed))
	if err != nil {
		return err
	}
	request.Header.Set("Content-Type", "application/json")
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}
	response, err := client.Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		return err
	}

	var result struct {
		Message string      `json:"message"`
		Code    int         `json:"code"`
		Data    interface{} `json:"data"`
	}
	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("解析响应体失败: %s", err.Error())
	}
	if result.Code != http.StatusOK {
		return fmt.Errorf("人工处理任务恢复报错: %s", result.Message)
	}
	return nil
}

// RetryJob 触发agent端重试作业
func RetryJob(ip string, retryReq *model.TaskRetryRequest, newJobId string) error {
	addr := fmt.Sprintf("http://%s:8277/plugin/automation/exec/job/retry", ip)

	// 构建请求数据，包含原作业信息和新作业ID
	requestData := struct {
		JobId    string `json:"job_id"`
		NewJobId string `json:"new_job_id"`
		StepNum  int    `json:"step_num"`
		ReuseEnv bool   `json:"reuse_env"`
	}{
		JobId:    retryReq.JobId,
		NewJobId: newJobId,
		StepNum:  retryReq.StepNum,
		ReuseEnv: retryReq.ReuseEnv,
	}

	dataMarshed, err := json.Marshal(requestData)
	if err != nil {
		return err
	}

	request, err := http.NewRequest("POST", addr, bytes.NewBuffer(dataMarshed))
	if err != nil {
		return err
	}

	request.Header.Set("Content-Type", "application/json")
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: true,
			},
		},
	}

	response, err := client.Do(request)
	if err != nil {
		return err
	}
	defer response.Body.Close()

	body, err := io.ReadAll(response.Body)
	if err != nil {
		return fmt.Errorf("读取响应体失败: %s", err.Error())
	}

	var result struct {
		Message string      `json:"message"`
		Code    int         `json:"code"`
		Data    interface{} `json:"data"`
	}

	if err := json.Unmarshal(body, &result); err != nil {
		return fmt.Errorf("解析响应体失败: %s", err.Error())
	}

	if result.Code != http.StatusOK {
		return fmt.Errorf("作业重试下发失败, 报错: %s", result.Message)
	}

	return nil
}
